﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace Common
{
    public class HebrewStemmer
    {
        public string[] prefixes;
        public char[,] finals = { { 'ן', 'נ' }, { 'ך', 'כ' }, { 'ץ', 'צ' }, { 'ף', 'פ' }, { 'ם', 'מ' } , { 'ה', 'ת' }, {'ת', 'ה'} };
        public string[] suffixes = { "ית", "ה", "ות", "ים", "יך", "ם", "ך", "יות" };
        public string PrefixFilePath;

        public HebrewStemmer(string prefixFilePath)
        {
            PrefixFilePath = prefixFilePath;
            Init();
        }
        private void Init()
        {
            prefixes = LoadPrefixFileToPrefixArray();
            
        }

        public List<string> GetStemmedWords(string word) //Includes English Stemmer
        {
            PorterStemmer ps = new PorterStemmer();
            word = ps.StemWord(word);
            List<string> result = new List<string>();
  
            //add original word
            if (word.Length > 1)
                result.Add(word);
            else 
                return result;
            //for original word, remove all suffixes.
             for (int j = 0; j < 0; j++)
                    {
                        if (word.EndsWith(suffixes[j]))
                        {
                             string suffixRemoved = word.Remove(word.LastIndexOf(suffixes[j]),
                                suffixes[j].Length);
                            //Check if final letter.
                            suffixRemoved = ReplaceEndingLetter(suffixRemoved);
                            if (suffixRemoved.Length > 1)
                            result.Add(suffixRemoved);
                        }
                    }
            for (int i = 0; i < prefixes.Length; i++)
            {
                if (word.StartsWith(prefixes[i])) //if word starts with prefix
                {
                    string prefixRemoved = word.Remove(word.IndexOf(prefixes[i]), prefixes[i].Length);
                    //add to list - prefix removed.
                    if (prefixRemoved.Length > 1)
                    result.Add(prefixRemoved); 
                    //For each 
                    for (int j = 0; j < 0; j++)
                    {
                        if (prefixRemoved.EndsWith(suffixes[j]))
                        {
                            string suffixRemoved = prefixRemoved.Remove(prefixRemoved.LastIndexOf(suffixes[j]),
                               suffixes[j].Length);
                            //Check if final letter.
                            suffixRemoved = ReplaceEndingLetter(suffixRemoved);
                            if (suffixRemoved.Length > 1)
                            result.Add(suffixRemoved);
                        }
                    }
                }

            }
            return result;
        }

        private string ReplaceEndingLetter(string word)
        {
            bool wordWithFinal = false;
            int finalsIndex = 0;

            for (int i = 0; i < finals.GetLength(0); i++) // check if word has ending letter.
            {
                if (word.EndsWith(finals[i, 1].ToString()))
                {
                    wordWithFinal = true; //ending letter.
                    finalsIndex = i;
                }
            }
            if (wordWithFinal) //if word with ending letter : 
            {
                word = word.Replace(finals[finalsIndex, 1], finals[finalsIndex, 0]); //replace final with non-final
            }
            return word;
        }

        public List<string> GetAllWordCombinations(string word)
        {
            string text = word;
            List<string> combinations = new List<string>();
            bool wordWithFinal = false;
            string toAdd;
            string tempWord;
            int finalsIndex = 0;


            combinations.Add(word); //Add clean word.
            for (int i = 0; i < finals.GetLength(0); i++) // check if word has ending letter.
            {
                if (text.EndsWith(finals[i, 0].ToString()))
                {
                    wordWithFinal = true; //ending letter.
                    finalsIndex = i;
                }
            }

            for (int j = 0; j < prefixes.Length + 1; j++) //add all single letter prefixes to text.
            {
                toAdd = text;
                if (j < prefixes.Length) // Once without a prefix.
                toAdd = toAdd.Insert(0, prefixes[j]); //Add a prefix.
                if (!combinations.Contains(toAdd))
                    combinations.Add(toAdd);
                if (wordWithFinal) //if word with ending letter : 
                {
                    toAdd = toAdd.Replace(finals[finalsIndex, 0], finals[finalsIndex, 1]); //replace final with non-final
                }

                for (int k = 0; k < suffixes.Length; k++) //add all suffixes.
                {
                    tempWord = toAdd;
                    tempWord = toAdd.Insert(toAdd.Length, suffixes[k]);
                    if (!combinations.Contains(tempWord))
                        combinations.Add(tempWord);

                }



            }

            /*Get all the word's suffixes and prefixes. (2 letters from beginning, 3 letters etc.)
            for (int i = 0; i < text.Length; i++)
            {
                combinations.Add(new Word(text.Substring(0, i)));
                combinations.Add(new Word(text.Substring(text.Length - i, i)));
            }
             */
            return combinations;

        }

        private string[] LoadPrefixFileToPrefixArray()
        {
            string filePath = PrefixFilePath;
            string line;
            List<string> prefixes = new List<string>();
            if (File.Exists(filePath))
            {
                StreamReader file = null;
                try
                {
                    file = new StreamReader(filePath);
                    while ((line = file.ReadLine()) != null)
                    {
                        prefixes.Add(line);
                    }
                }
                finally
                {
                    if (file != null)
                        file.Close();
                }
            }

            return prefixes.ToArray();
        }
    }
}
